package com.kwq.shixi.util;


import com.kwq.shixi.model.ExcelSheetPO;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import org.joda.time.DateTime;
import org.springframework.web.multipart.MultipartFile;


import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Excel读写工具类
 * @author gothiconezq
 */
public class ExcelUtil {

    public static void main(String[] args) {


    }
    /**
     * 标题样式
     */
    private final static String STYLE_HEADER = "header";
    /**
     * 表头样式
     */
    private final static String STYLE_TITLE = "title";
    /**
     * 数据样式
     */
    private final static String STYLE_DATA = "data";

    /**
     * 存储样式
     */
    private static final HashMap<String, CellStyle> cellStyleMap = new HashMap<>();


    /**
     * 在线读取excel文件里面的内容 支持日期，数字，字符，函数公式，布尔类型
     *
     * @param file
     * @param rowCount 读取指定行数
     * @param columnCount 读取指定列数
     * @return
     * @throws FileNotFoundException
     * @throws IOException
     * 参考博客： https://blog.csdn.net/weixin_38379125/article/details/78773351
     */
    public static List<ExcelSheetPO> readExcelOnLine(MultipartFile file, Integer rowCount, Integer columnCount)
            throws IOException {

        // 获取后缀名
        // 根据后缀名称判断excel的版本
        String extName = FileUtil.getMultipartFileExtName(file);
        Workbook wb = null;
        if (ExcelVersion.V2003.getSuffix().equals(extName)) {
            wb = new HSSFWorkbook(file.getInputStream());

        } else if (ExcelVersion.V2007.getSuffix().equals(extName)) {
            wb = new XSSFWorkbook(file.getInputStream());

        } else {
            // 无效后缀名称，这里之能保证excel的后缀名称，不能保证文件类型正确，不过没关系，在创建Workbook的时候会校验文件格式
            throw new IllegalArgumentException("Invalid excel version");
        }
        // 开始读取数据
        List<ExcelSheetPO> sheetPOs = new ArrayList<>();
        // 解析sheet
        for (int i = 0; i < wb.getNumberOfSheets(); i++) {
            Sheet sheet = wb.getSheetAt(i);
            List<List<Object>> dataList = new ArrayList<>();
            ExcelSheetPO sheetPO = new ExcelSheetPO();
            sheetPO.setSheetName(sheet.getSheetName());
            sheetPO.setDataList(dataList);
            int readRowCount = 0;
            if (rowCount == null || rowCount > sheet.getPhysicalNumberOfRows()) {
                // 获取真实有效的行数
                readRowCount = getRealValidRowCount(sheet);

            } else {
                readRowCount = rowCount;
            }
            // 解析sheet 的行
            //sheet.getFirstRowNum() 获取第一个实际行的下标
            for (int j = sheet.getFirstRowNum()+1; j <= readRowCount; j++) {
                Row row = sheet.getRow(j);
                if (row == null) {
                    continue;
                }
                //getFirstCellNum 获取在某行第一个单元格的下标

                if (row.getFirstCellNum() < 0) {
                    continue;
                }
                int readColumnCount = 0;
                //getLastCellNum 获取在某行的列数
                if (columnCount == null || columnCount > row.getLastCellNum()) {
                    readColumnCount = (int) row.getLastCellNum();
                } else {
                    readColumnCount = columnCount;
                }
                List<Object> rowValue = new LinkedList<Object>();
                // 解析sheet 的列
                for (int k = 0; k < readColumnCount; k++) {
                    Cell cell = row.getCell(k);
                    rowValue.add(getCellValue(wb, cell));
                }
                dataList.add(rowValue);
            }
            sheetPOs.add(sheetPO);
        }
        return sheetPOs;
    }
    /**
     * 获取真实有效的行数
     * @param sheet
     * @return
     */
    private static int getRealValidRowCount(Sheet sheet){


        boolean flag = false;
        for (int i = 0; i < sheet.getLastRowNum(); ) {
            Row r = sheet.getRow(i);
            if (r == null) {
                // 如果是空行（即没有任何数据、格式），直接把它以下的数据往上移动
                sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
                continue;
            }
            flag = false;
            for (Cell c : r) {
                if (c.getCellType() != Cell.CELL_TYPE_BLANK) {
                    flag = true;
                    break;
                }
            }
            if (flag) {
                i++;
                continue;
            } else {//如果是空白行（即可能没有数据，但是有一定格式）
                //如果到了最后一行，直接将那一行remove掉
                if (i == sheet.getLastRowNum()) {
                    sheet.removeRow(r);
                }else {//如果还没到最后一行，则数据往上移一行
                    sheet.shiftRows(i + 1, sheet.getLastRowNum(), -1);
                }
            }
        }
        /*System.out.println("有效行数为："+sheet.getLastRowNum());*/
        return sheet.getLastRowNum() ;
    }

    /*返回正确的字段类型*/
    private static Object getCellValue(Workbook wb, Cell cell) {
        Object columnValue = null;
        if (cell != null) {
            // 格式化 number
            DecimalFormat df = new DecimalFormat("0");
            // String
            // 格式化日期字符串
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            // 格式化数字
            DecimalFormat nf = new DecimalFormat("0.00");
            switch (cell.getCellType()) {
                //字符串
                case Cell.CELL_TYPE_STRING:
                    columnValue = cell.getStringCellValue();
                    System.out.println("String=>"+columnValue);
                    break;

                case HSSFCell.CELL_TYPE_NUMERIC://数字(日期、普通数字)
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {// 日期
                        Date date = cell.getDateCellValue();
                        columnValue = new DateTime(date).toString("yyyy-MM-dd");
                        System.out.println("日期："+columnValue);
                    } else {
                        //不是日期格式，防止数字过长 转化为字符串！
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        columnValue = cell.toString();
                        System.out.println("数字转化为字符串"+columnValue);
                    }
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    columnValue = cell.getBooleanCellValue();
                    System.out.println("boolean:"+columnValue);
                    break;
                case Cell.CELL_TYPE_BLANK:
                    columnValue = "";
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    // 格式单元格
                    FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
                    evaluator.evaluateFormulaCell(cell);
                    CellValue cellValue = evaluator.evaluate(cell);
                    //返回double
                    columnValue = cellValue.getNumberValue();
                    System.out.println("FORMULA："+columnValue);
                    break;
                default:
                    columnValue = cell.toString();
            }
        }
        return columnValue;
    }
}
